import json
import os
import re
import configparser
from api_test.models import TestPlanConf
from .util import Util


def add_service():
    dir_path = os.path.join(os.path.split(os.path.dirname(__file__))[0], 'config')
    json_path = os.path.join(dir_path, 'service.yaml')
    ini_path = os.path.join(dir_path, 'conf.ini')
    cfg = Util().read_yaml_config(json_path)
    config = configparser.ConfigParser()
    config.read(ini_path)
    use_local = config.getboolean('service', 'use_local')
    service_type = 'local' if use_local else 'remote'
    host = config.get('service', service_type)
    conf = json.dumps(cfg)
    globals()['service'] = json.loads(re.sub('{host}', host, conf))


def generate_update_req_json_content(param_path, params_content, kew_word, content):
    code = '${code}'
    for var in param_path:
        key = var.get('key')
        value = var.get('value')
        if '${__RandomString(' in value:
            random_str = '${random_string}'
            length = int(value.split('(')[-1].split(')')[0])
            params_content += f'\t{random_str} =  generate string  {length}\n' + \
                              f'\tupdate req json  {kew_word}  {key}={random_str}\n'
        elif value == '${__UUID}':
            random_uuid = '${random_uuid}'
            params_content += f'\t{random_uuid} =  generate uuid\n' + \
                              f'\tupdate req json  {kew_word}  {key}={random_uuid}\n'
        else:
            params_content += f'\tupdate req json  {kew_word}  {key}={value}\n'
    content += params_content + f'\tWhen {kew_word}\n' + \
                                f'\t{code} =  parse resp json  code\n' + \
                                f'\tstr assert  {code}  999999\n'
    return content


def generate_global_variable_content(content, data):
    params_content = ''
    for param in data.get('globalVariable'):
        key = '${' + param.get('key') + '}'
        index = param.get('index')
        value = param.get('value')
        flag = param.get('flag', True)
        if flag:
            if index:
                params_content += f'\t{key} =  parse resp json  {value}  {index}\n'
            else:
                params_content += f'\t{key} =  parse resp json  {value}\n'
            params_content += f'\tset suite variable  {key}\n'
    content += params_content
    return content


def generate_response_assert_content(content, data, code):
    params_content = ''
    i = 0
    key_list = []
    for var in data.get('responseAssert'):
        i += 1
        key = var.get('key')
        value = var.get('value')
        index = var.get('index', 0)
        param = "${param_" + str(i + 1) + "}"
        flag = var.get('flag', True)
        if flag:
            key_list.append(key)
            params_content += f'\t{param} =  parse resp json  {key}  {index}\n' + \
                              f'\tstr assert  {param}  {value}\n'
    if 'code' not in key_list:
        params_content += f'\t{code} =  parse resp json  code\n' + \
                              f'\tstr assert  {code}  999999\n'
    content += params_content
    return content


def generate_content(content, data, code):
    if data.get('responseAssert'):
        content = generate_response_assert_content(content, data, code)
    else:
        content += f'\t{code} =  parse resp json  code\n' + \
                   f'\tstr assert  {code}  999999\n'
    if data.get('globalVariable'):
        content = generate_global_variable_content(content, data)
    return content


def generate_robot_file(data_list, plan_name, plan_id):
    suite_dir = os.path.join(os.path.split(os.path.dirname(__file__))[0], 'suites')
    file_path = os.path.join(suite_dir, f'{plan_name.lower()}'+'.robot')
    case_index = 1
    num = ''
    config = TestPlanConf.objects.filter(plan_id=plan_id)
    params = json.loads(config[0].param) if config else {}
    content = '*** Settings ***\n' + \
              f'Documentation   CaseList of {plan_name}\n' + \
              'Library          api_test.common.test_plan_case_processor.TestPlanCaseProcessor\n' + \
              'Library          api_test.common.util.Util\n' + \
              'Resource         resource/resource.robot\n' + \
              'Test Teardown    Log Response Info\n' + \
              '\n*** Test Cases ***\n'

    for data in data_list:
        if case_index in range(10):
            num = f'00{case_index}'
        elif case_index in range(10, 100):
            num = f'0{case_index}'
        elif case_index in range(100, 1000):
            num = str(case_index)
        kew_word = f'TestPlan{plan_id}_Case{data.get("index")}'
        description = data.get('description') if data.get('description') else data.get('name')
        param_path = Util().get_request_params_path(data['request']['body'])
        code = '${code}'
        if case_index == 1:
            if params:
                params_content = f'{plan_name}_{num}\n' + \
                                 f'\t[Tags]  {plan_name}\n' + \
                                 f'\t[Documentation]  {description}\n'
                for key, value in params.items():
                    key_format = '${' + key + '}'
                    if '${__RandomString(' in value:
                        length = int(value.split('(')[-1].split(')')[0])
                        val = Util.generate_string(length)
                    elif value == '${__UUID}':
                        val = Util.generate_uuid()
                    else:
                        val = value
                    value_format = '${' + str(val) + '}' if isinstance(val, int) else val
                    params_content += f'\tset suite variable  {key_format}  {value_format}\n'
                content = generate_update_req_json_content(param_path, params_content, kew_word, content)
            else:
                content += f'{plan_name}_{num}\n' + \
                           f'\t[Tags]  {plan_name}\n' + \
                           f'\t[Documentation]  {description}\n' + \
                           f'\tWhen {kew_word}\n'
            content = generate_content(content, data, code)
        else:
            if param_path:
                params_content = f'{plan_name}_{num}\n' + \
                                 f'\t[Tags]  {plan_name}\n' + \
                                 f'\t[Documentation]  {description}\n'
                content = generate_update_req_json_content(param_path, params_content, kew_word, content)
            else:
                content += f'{plan_name}_{num}\n' + \
                           f'\t[Tags]  {plan_name}\n' + \
                           f'\t[Documentation]  {description}\n' + \
                           f'\tWhen {kew_word}\n'
            content = generate_content(content, data, code)
        content += '\n'
        case_index += 1
    with open(file_path, 'w') as f:
        f.write(content)
